package com.itlong.cloud.controller.home;

import com.itlong.cloud.POJO.DTO.app.MiniSetVisitPassFaceDTO;
import com.itlong.cloud.POJO.DTO.common.PadFaceSyncDataDTO;
import com.itlong.cloud.POJO.DTO.property.PropertyAddVisitorDTO;
import com.itlong.cloud.POJO.PO.AppVisitorPassCodeRecordPO;
import com.itlong.cloud.POJO.PO.ProjectPO;
import com.itlong.cloud.POJO.VO.MessageVO;
import com.itlong.cloud.POJO.VO.app.AppCreateBaiduFaceVO;
import com.itlong.cloud.POJO.VO.app.AppFloorDevicesVO;
import com.itlong.cloud.POJO.VO.app.AppUserCacheVO;
import com.itlong.cloud.POJO.VO.operate.OperateFaceApplyInfoVO;
import com.itlong.cloud.POJO.VO.property.PropertyUserCacheVO;
import com.itlong.cloud.POJO.VO.property.PropertyVisitorSendMessageVO;
import com.itlong.cloud.PlatformConstants;
import com.itlong.cloud.abstracts.BaseController;
import com.itlong.cloud.annotation.AuthAccessRequired;
import com.itlong.cloud.annotation.LoggerInfo;
import com.itlong.cloud.constants.LogDescConstant;
import com.itlong.cloud.constants.RedisConstant;
import com.itlong.cloud.enumerate.FileCatalogEnum;
import com.itlong.cloud.enumerate.LanguageTypeEnum;
import com.itlong.cloud.enumerate.ecode.AppErrorCodeEnum;
import com.itlong.cloud.enumerate.ecode.BaseErrorCodeEnum;
import com.itlong.cloud.enumerate.ecode.ErrorCode;
import com.itlong.cloud.enumerate.ecode.PropertyErrorCodeEnum;
import com.itlong.cloud.enumerate.ecode_en.AppErrorCodeEnumEN;
import com.itlong.cloud.enumerate.ecode_en.BaseErrorCodeEnumEN;
import com.itlong.cloud.equip.app.IAppVisitorPassCodeRecordServiceClient;
import com.itlong.cloud.equip.property.IPadFaceSyncDataServiceClient;
import com.itlong.cloud.iottp.IIotBaiduFaceServiceClient;
import com.itlong.cloud.iottp.IIotTpSmsServiceClient;
import com.itlong.cloud.project.operate.IOperateFaceApplyServiceClient;
import com.itlong.cloud.project.operate.IOperateProjectServiceClient;
import com.itlong.cloud.service.RedisService;
import com.itlong.cloud.thrown.DataAccessException;
import com.itlong.cloud.user.app.IAppUserInfoCacheServiceClient;
import com.itlong.cloud.user.property.IPropertyVisitorServiceClient;
import com.itlong.cloud.user.propertyapp.IPropertyAppUserInfoServiceClient;
import com.itlong.cloud.utils.encrypt.Md5EncryptUtil;
import com.itlong.cloud.utils.encrypt.UserTokenUtil;
import com.itlong.cloud.utils.file.UploadFileUtil;
import com.itlong.cloud.utils.network.http.HttpProtocolUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import sun.misc.BASE64Decoder;

import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.URLDecoder;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * <desc>
 *      物业APP首页版块访客登记模块控制器
 * </desc>
 *
 * @create 2019/12/31
 */
@RestController
@RequestMapping("/home")
@RefreshScope
public class PropertyAppVisitorController extends BaseController {

    private static final Logger LOG = LoggerFactory.getLogger(PropertyAppVisitorController.class);

    @Value("${"+ PlatformConstants.PROPERTY_APP_USER_TOKEN_KEY +"}")
    private String propertyAppUserTokenKey;

    @Value("${" + PlatformConstants.FILE_FTP_HOST + "}")
    public String FILE_FTP_HOST;
    @Value("${" + PlatformConstants.FILE_FTP_PORT + "}")
    public String FILE_FTP_PORT;
    @Value("${" + PlatformConstants.FILE_FTP_USERNAME + "}")
    public String FILE_FTP_USERNAME;
    @Value("${" + PlatformConstants.FILE_FTP_PASSWORD + "}")
    public String FILE_FTP_PASSWORD;
    @Value("${" + PlatformConstants.FILE_ACCESS_URL + "}")
    public String FILE_ACCESS_URL;

    @Autowired
    IAppUserInfoCacheServiceClient userCache;

    @Autowired
    IPropertyAppUserInfoServiceClient iPropertyAppUserInfoServiceClient;

    @Autowired
    IPropertyVisitorServiceClient iPropertyVisitorServiceClient;

    @Autowired
    IIotTpSmsServiceClient iIotTpSmsServiceClient;

    @Autowired
    IOperateFaceApplyServiceClient iOperateFaceApplyServiceClient;

    @Autowired
    IIotBaiduFaceServiceClient iIotBaiduFaceServiceClient;

    @Autowired
    IAppVisitorPassCodeRecordServiceClient iAppVisitorPassCodeRecordServiceClient;

    @Autowired
    IOperateProjectServiceClient iOperateProjectServiceClient;

    @Autowired
    IPadFaceSyncDataServiceClient iPadFaceSyncDataServiceClient;

    /**
     * <desc>
     *      保存访客
     * </desc>
     * @param propertyAddVisitorDTO
     * @return
     * @throws Exception
     * @author Juguang.S
     * @createDate 2019/12/30
     */
    @ResponseBody
    @PostMapping(path = "visitorRegistration")
    @LoggerInfo(operateDesc = LogDescConstant.SAVE_VISITOR_INFO_DESC)
    public Object addVisitor(PropertyAddVisitorDTO propertyAddVisitorDTO) throws Exception {
        LOG.info("【物业APP上传访客人脸入口】");
        MessageVO messageVO;
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            propertyAddVisitorDTO = HttpProtocolUtil.parseRequestParamToDTO(PropertyAddVisitorDTO.class, request);
            if (propertyAddVisitorDTO == null) {
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            PropertyUserCacheVO propertyUserCacheVO = iPropertyAppUserInfoServiceClient.retrieve(propertyAddVisitorDTO.getToken());
            String userId = propertyUserCacheVO.getUserId();
            propertyAddVisitorDTO.setLoginUserId(userId);
            propertyAddVisitorDTO.setSourceType(2);
            AppVisitorPassCodeRecordPO po = iPropertyVisitorServiceClient.addVisitor(propertyAddVisitorDTO);
            PropertyVisitorSendMessageVO sendMessageVO = iPropertyVisitorServiceClient.getVisitorMessage(po.getPassId());
            String content = "您的访客通行密码:"+sendMessageVO.getPassword()+"，用于"+sendMessageVO.getAddress()+"。有效时间为"+sendMessageVO.getStartTime()+"至"+sendMessageVO.getEndTime()+"前。点击链接"+sendMessageVO.getQrcodeUrl()+" ，查看访客二维码，您也可通过扫描该二维码进行通行";
            if(StringUtils.isNotEmpty(sendMessageVO.getVisitorPhone())){
                iIotTpSmsServiceClient.sendSmsCodeByPhone(sendMessageVO.getVisitorPhone(),content);
            }
            Map<String,Object> result = new HashMap<>();
            result.put("passId",po.getPassId());

            if (propertyAddVisitorDTO.getImageStr() != null && !"".equals(propertyAddVisitorDTO.getImageStr())) {
                MiniSetVisitPassFaceDTO miniSetVisitPassFaceDTO = new MiniSetVisitPassFaceDTO();
                miniSetVisitPassFaceDTO.setImageStr(propertyAddVisitorDTO.getImageStr());
                miniSetVisitPassFaceDTO.setPassId(po.getPassId());
                miniSetVisitPassFaceDTO.setProjectId(propertyAddVisitorDTO.getProjectId());
                miniSetVisitPassFaceDTO.setIdcardKey(propertyAddVisitorDTO.getIdcardKey());
                LOG.info("【物业APP上传访客人脸处理人脸注册】");
                messageVO = this.setVisitPassFacePrivate(miniSetVisitPassFaceDTO);
                if (messageVO.getMsgCode() != 0) {
                    iAppVisitorPassCodeRecordServiceClient.deleteVisitorInfo(po.getPassId());
                    return messageVO;
                }
            }

            return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(), result);
        } catch (Exception e) {
            throw new DataAccessException("【物业APP_首页版块访客登录模块_保存访客】失败", e);
        }
    }

    /**
     * <desc>
     *      保存访客人脸(私有)
     * </desc>
     *
     * @param dto 接收数据dto类
     * @return
     * @author Juguang.S
     * @createDate 2019/12/30
     */
    private MessageVO setVisitPassFacePrivate(MiniSetVisitPassFaceDTO dto) throws Exception{
        LOG.info("【物业APP上传访客人脸】");
        if (StringUtils.isBlank(dto.getImageStr())){
            return new MessageVO(AppErrorCodeEnum.IMAGE_DATA_INVALID.getErrorCode());
        }
        Map<String, String> map = new HashMap<>();
        //判断项目是否开启人脸识别,并查询是否有百度库key
        OperateFaceApplyInfoVO operateFaceApplyInfoVO = iOperateFaceApplyServiceClient.getFaceByProjectId(dto.getProjectId());
        if(operateFaceApplyInfoVO == null){
            ErrorCode errorCode = AppErrorCodeEnum.PROJECT_FACE_APPID_INEXISTENCE.getErrorCode();
            return new MessageVO(errorCode);
        }
        //判断图片是否合格
//        String[] imageStrS = dto.getImageStr().split(",");
//        dto.setImageStr(imageStrS[1]);
        //访客人脸注册时,判断人脸库中是否有此人数据
        AppCreateBaiduFaceVO appCreateBaiduFaceVO = new AppCreateBaiduFaceVO();
        appCreateBaiduFaceVO.setAPP_ID(operateFaceApplyInfoVO.getAppId());
        appCreateBaiduFaceVO.setAPI_KEY(operateFaceApplyInfoVO.getApiKey());
        appCreateBaiduFaceVO.setSECRET_KEY(operateFaceApplyInfoVO.getSecretKey());
        appCreateBaiduFaceVO.setFaceScore(operateFaceApplyInfoVO.getFaceScore()==0F?80F:operateFaceApplyInfoVO.getFaceScore());
//        appCreateBaiduFaceVO.setFile(new BASE64Decoder().decodeBuffer(dto.getImageStr()));
        String uploadFilePath = uploadImageFile(dto.getImageStr(), "jpg", FileCatalogEnum.BAIDU_FACE_CREATE_FILE);
        appCreateBaiduFaceVO.setImageUrl(uploadFilePath);
        if (StringUtils.isBlank(uploadFilePath)) {
            return new MessageVO(AppErrorCodeEnum.IMAGE_UPLOAD_FAILED.getErrorCode());
        }
        String checkResult = iIotBaiduFaceServiceClient.faceVerify(appCreateBaiduFaceVO);
        if (checkResult != null && !"".equals(checkResult)) {
            if ("error".equals(checkResult)) {//调用接口异常
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_FACEVERFY_ERROR.getErrorCode());
            }
            if ("busy".equals(checkResult)) {//调用接口忙
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_BAIDU_BUSY.getErrorCode());
            }
            if ("others".equals(checkResult)) {//图片不合格,非真人图片
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_BAIDU_PICTURE_ERROR.getErrorCode());
            }
            if ("result_num".equals(checkResult)) {//人脸数异常
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_FACE_RESULTNUM_NOT_1.getErrorCode());
            }
            if ("size".equals(checkResult)) {//人脸太小
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_FACE_SIZE_TOO_SMALL.getErrorCode());
            }
            //2020年8月5号 按照需求说明取消活体检测
           /* if ("faceliveness".equals(checkResult)) {//活体值异常
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_FACE_FACELIVENESS_TOO_LOW.getErrorCode());
            }*/
            if ("left_eye".equals(checkResult) || "right_eye".equals(checkResult) || "nose".equals(checkResult)
                    || "mouth".equals(checkResult) || "left_cheek".equals(checkResult) || "right_cheek".equals(checkResult)
                    || "chin".equals(checkResult)) {//图片遮挡
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_FACE_OCCLUSION.getErrorCode());
            }
            if ("blur".equals(checkResult)) {//模糊
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_FACE_BLUR_TOO_LOW.getErrorCode());
            }
            if ("illumination_min".equals(checkResult)) {//光照过暗
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_FACE_ILLUMINATION_TOO_LOW.getErrorCode());
            }
            if ("illumination_max".equals(checkResult)) {//光照过亮
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_FACE_ILLUMINATION_TOO_HIGH.getErrorCode());
            }
            if ("pitch".equals(checkResult) || "roll".equals(checkResult) || "yaw".equals(checkResult)) {//角度
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_FACE_ANGLE_NOT_STRAIGHT.getErrorCode());
            }
            if ("completeness".equals(checkResult)) {//人脸完整度
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_FACE_COMPLETENESS_IMPERFECT.getErrorCode());
            }
        }
        String repeatResult = iIotBaiduFaceServiceClient.identifyUser(appCreateBaiduFaceVO);//拿到现有的id
        if (repeatResult != null && !"".equals(repeatResult)) {
            if ("error".equals(repeatResult)) {//调用接口异常
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_IDENTIFY_ERROR.getErrorCode());
            }
            if ("busy".equals(repeatResult)) {//调用接口忙
                return new MessageVO(PropertyErrorCodeEnum.APPUSER_BAIDU_BUSY.getErrorCode());
            }
        }
        String vFaceId;
        //判断认证图片是否重复
        if (repeatResult == null) {//人脸库中无此人脸ID使用V_ + pass_id
            appCreateBaiduFaceVO.setUid("V_"+dto.getPassId());
            //创建百度人脸信息
            boolean result = iIotBaiduFaceServiceClient.doCreateBaiduFaceForVisitor(appCreateBaiduFaceVO);
            if (!result) {
                map.put("result","2");
                return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(),map);
            }
            vFaceId = appCreateBaiduFaceVO.getUid();
        }else {//人脸库中有此人脸
            //有此人脸时证明这个人在此项目中注册过人脸业主使用的是这个人的user_id,访客使用的是V_ + pass_id   不进行重复注册
            if (repeatResult.substring(0,2).equals("V_")) {//访客人脸则进行覆盖
                appCreateBaiduFaceVO.setUid(repeatResult);
                //创建百度人脸信息
                boolean result = iIotBaiduFaceServiceClient.doCreateBaiduFaceForVisitor(appCreateBaiduFaceVO);
                if (!result) {
                    map.put("result","2");
                    return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(),map);
                }
            }
            vFaceId = repeatResult;
        }
        iAppVisitorPassCodeRecordServiceClient.setVisitPassFace(dto.getPassId(), uploadFilePath, vFaceId, dto.getProjectId(), dto.getIdcardKey()==null?"":dto.getIdcardKey(),0);

        Date currentTime = new Date();
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        map.put("authDate",formatter.format(currentTime));
        map.put("result","1");
        map.put("uploadFilePath",uploadFilePath);
        //查询当前项目信息
        ProjectPO projectPO = iOperateProjectServiceClient.getOneProject(dto.getProjectId());
        // 平板优先离线，则插入同步数据
        if (projectPO.getOnOffLinePadFace() != null) {
            PadFaceSyncDataDTO padFaceSyncDataDTO = new PadFaceSyncDataDTO();
            padFaceSyncDataDTO.setOperateType("3");
            padFaceSyncDataDTO.setProjectId(dto.getProjectId());
            padFaceSyncDataDTO.setPassId(dto.getPassId());
            padFaceSyncDataDTO.setStatus("1");
            padFaceSyncDataDTO.setSourceSystem(0);
            if(projectPO.getOnOffLinePadFace() == 1){
                iPadFaceSyncDataServiceClient.userOrFloorSync(padFaceSyncDataDTO);
            }
            iPadFaceSyncDataServiceClient.userOrFloorSyncSmartCard(padFaceSyncDataDTO);
        }
        return new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(),map);
    }

    /**
     * <desc>
     *      人脸认证权限验证。
     * <desc/>
     *
     * @param projectId 项目ID
     * @return
     * @author Juguang.S
     * @createDate 2020/03/20
     */
    @RequestMapping(path ="/cteateBaiduFaceVerify")
    @ResponseBody
    public Object cteateBaiduFaceVerify(String projectId) {
        MessageVO messageVO;
        try {
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            projectId = request.getAttribute("projectId") == null ? null : request.getAttribute("projectId").toString();
            if(StringUtils.isEmpty(projectId)){
                return new MessageVO(BaseErrorCodeEnum.NOT_PARAM.getErrorCode());
            }
            OperateFaceApplyInfoVO operateFaceApplyInfoVO = iOperateFaceApplyServiceClient.getFaceByProjectId(projectId);
            messageVO = new MessageVO(BaseErrorCodeEnum.SUCCESS.getErrorCode(),operateFaceApplyInfoVO);
        } catch (Exception e) {
            throw new DataAccessException("【物业App_cteateBaiduFaceVerify】人脸认证权限验证", e);
        }
        return  messageVO;
    }

    /**
     * <desc>
     *      上传图片文件
     * <desc/>
     *
     * @param imageStr 图片二进制
     * @param imageType 图片类型
     * @return
     * @author Chunjian.G
     * @createDate 2017-11-10
     */
    private String uploadImageFile(String imageStr,String imageType, FileCatalogEnum fileCatalog){
        try {
            imageStr = URLDecoder.decode(imageStr, "UTF-8");
        }catch (Exception e){
            LOG.info("imageStr URLDecoder失败", e);
            return null;
        }
        byte[] bytes = null;
        try {
            bytes = new BASE64Decoder().decodeBuffer(imageStr);
        } catch (IOException e) {
            LOG.info("BASE64Decoder().decodeBuffer失败,imageStr不合法", e);
            return null;
        }
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
        UploadFileUtil.UploadFile uploadFileUtil = new UploadFileUtil().new UploadFile(
                FILE_FTP_HOST,
                FILE_FTP_USERNAME,
                FILE_FTP_PASSWORD,
                FILE_FTP_PORT,
                byteArrayInputStream,
                imageType,
                FILE_ACCESS_URL,
                fileCatalog.getType()
        );
        try {
            LOG.info("正在上传图片");
            Map<String, Object> resultMap = UploadFileUtil.uploadFile(uploadFileUtil);
            LOG.info("图片上传完毕");
            String returnCode = resultMap.get("returnCode").toString();
            if ("true".equals(returnCode)){
                String fileUrl = resultMap.get("accessPath").toString();
                return fileUrl;
            }else {
                LOG.info(String.format("图片上传失败，returnCode: %s",returnCode));
                return null;
            }
        } catch (IOException e) {
            LOG.info("UploadFileUtil.uploadFile失败", e);
            return null;
        }
    }
}
